﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BushakwiaRLF
{
    public delegate void ImageHoverEvent(Point location);

    //public delegate void ViewOptionChangedEvent(Metrics metric, Directions direction);

    public partial class ResultForm : Form
    {
        private event ImageHoverEvent ImageHover;

        private const int MAX_COLOR = 255;

        private RLFClient rlf;

        private Metrics Metric
        {
            get
            {
                if (radioButtonSPE.Checked) return Metrics.ShortPrimitiveEmphasis;
                if (radioButtonLPE.Checked) return Metrics.LongPrimitiveEmhasis;
                if (radioButtonGLU.Checked) return Metrics.GrayLevelUniformity;
                if (radioButtonPLU.Checked) return Metrics.PrimitiveLengthUniformity;
                return Metrics.PrimitivePercentage;
            }
        }

        private Directions Direction
        {
            get
            {
                if (radioButtonVertical.Checked) return Directions.Vertical;
                if (radioButtonHorizontal.Checked) return Directions.Horizontal;
                return Directions.Both;
            }
        }

        public ResultForm(RLFClient rlf)
        {
            InitializeComponent();
            this.rlf = rlf;
            DisplaySelectedImage();
            ImageHover += displayImageMetrics;
        }

        private void displayImageMetrics(Point location)
        {
            Directions direction = Direction;

            foreach (Metrics metric in Enum.GetValues(typeof(Metrics)))
            {
                var key = new Tuple<Directions, Metrics>(direction, metric);

                float metricValue = this.rlf.RlfImages[key].GetPixel(location.X, location.Y).R;
                metricValue /= (float)MAX_COLOR;
                string formattedValue = metricValue.ToString("0.0000");

                switch (metric)
                {
                    case Metrics.ShortPrimitiveEmphasis:
                        labelSPEValue.Text = formattedValue;
                        break;
                    case Metrics.LongPrimitiveEmhasis:
                        labelLPEValue.Text = formattedValue;
                        break;
                    case Metrics.GrayLevelUniformity:
                        labelGLUValue.Text = formattedValue;
                        break;
                    case Metrics.PrimitiveLengthUniformity:
                        labelPLUValue.Text = formattedValue;
                        break;
                    default:
                        labelPPValue.Text = formattedValue;
                        break;
                }
            }
        }

        private void resultPictureBox_MouseMove(object sender, MouseEventArgs e)
        {
            Point p = translateZoomMousePosition(e.Location, resultPictureBox);
            if (ImageHover != null)
            {
                ImageHover(p);
            }
        }

        private Point translateZoomMousePosition(Point coordinates, PictureBox pictureBox)
        {
            Image image = pictureBox.Image;
            // test to make sure our image is not null
            if (image == null) return coordinates;
            // Make sure our control width and height are not 0 and our 
            // image width and height are not 0
            if (pictureBox.Width == 0 || pictureBox.Height == 0 || image.Width == 0 || image.Height == 0) return coordinates;
            // This is the one that gets a little tricky. Essentially, need to check 
            // the aspect ratio of the image to the aspect ratio of the control
            // to determine how it is being rendered
            float imageAspect = (float)image.Width / image.Height;
            float controlAspect = (float)pictureBox.Width / pictureBox.Height;
            float newX = coordinates.X;
            float newY = coordinates.Y;
            if (imageAspect > controlAspect)
            {
                // This means that we are limited by width, 
                // meaning the image fills up the entire control from left to right
                float ratioWidth = (float)image.Width / pictureBox.Width;
                newX *= ratioWidth;
                float scale = (float)pictureBox.Width / image.Width;
                float displayHeight = scale * image.Height;
                float diffHeight = pictureBox.Height - displayHeight;
                diffHeight /= 2;
                newY -= diffHeight;
                newY /= scale;
            }
            else
            {
                // This means that we are limited by height, 
                // meaning the image fills up the entire control from top to bottom
                float ratioHeight = (float)image.Height / pictureBox.Height;
                newY *= ratioHeight;
                float scale = (float)pictureBox.Height / image.Height;
                float displayWidth = scale * image.Width;
                float diffWidth = pictureBox.Width - displayWidth;
                diffWidth /= 2;
                newX -= diffWidth;
                newX /= scale;
            }
            return new Point((int)clamp(newX, 0, image.Width-1), (int)clamp(newY, 0, image.Height-1));
        }

        private float clamp(float value, float min, float max)
        {
            return value < min ? min : (value > max ? max : value);
        }

        private void DisplaySelectedImage()
        {
            var key = new Tuple<Directions, Metrics>(Direction, Metric);
            resultPictureBox.Image = this.rlf.RlfImages[key];
        }

        private void radioButton_CheckedChanged(object sender, EventArgs e)
        {
            //if (ViewOptionChanged != null)
            //{
            //    ViewOptionChanged(Metric, Direction);
            //}
            DisplaySelectedImage();            
        }
    }
}
